home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / c / rdcf.exe / RDCF2.DOC < prev    next >
Text File  |  1993-01-15  |  72KB  |  1,680 lines

  1.           RDCF: A Reentrant DOS-Compatible File System, Version 2.0
  2.  
  3.                             by Philip J. Erdelsky
  4.                           PLAIN VANILLA CORPORATION
  5.                             CompuServe 75746,3411
  6.                       InterNet 75746.3411@compuserve.com
  7.  
  8.                                January 15, 1993
  9.  
  10.                  Copyright (c) 1993 Plain Vanilla Corporation
  11.  
  12.  
  13.  
  14. 1. Introduction
  15. ---------------
  16.  
  17. RDCF is a reentrant and ROMable DOS-compatible file system designed for use
  18. with floppy diskettes and hard disk partitions that do not exceed 32 Mbytes in
  19. size.
  20.  
  21. For users who are familiar with version 1.0, here is a summary of the
  22. differences between versions 1.0 and 2.0:
  23.  
  24.   (1) Version 2.0 supports subdirectories and volume names.  This is by far
  25.       the most important difference.
  26.  
  27.   (2) Version 2.0 can be compiled to adapt to different sector sizes at run
  28.       time.
  29.  
  30.   (3) Version 2.0 has no default drive option, but it can be compiled with or
  31.       without multiple drive support.
  32.  
  33.   (4) The parameters to some functions have been changed slightly to make them
  34.       more uniform.
  35.  
  36.   (5) Version 2.0 requires access to the system clock, although a dummy access
  37.       function will suffice for systems without clocks.
  38.  
  39.   (6) In version 2.0, the drive access function pointer is stored in the file
  40.       control block by the calling program, instead of being passed as a
  41.       parameter.
  42.  
  43.   (7) In version 2.0, direct access to the file control block is not encouraged
  44.       to the extent it was in version 1.0.
  45.  
  46.   (8) Version 2.0 has a few additional features, such as a directory sort
  47.       function, that were not in version 1.0 and are not in most
  48.       implementations of DOS.
  49.  
  50.   (9) Version 2.0 is copyrighted. Although you may use it non-commercially
  51.       without registering it or paying any fees, resale or commercial use
  52.       requires permission and payment of a one-time royalty.
  53.  
  54. Although DOS 3 permits characters from the IBM extended character set in file
  55. names, most DOS applications don't, and neither does RDCF.
  56.  
  57. Since DOS 1 is now obsolete, RDCF does not support DOS 1 diskette formats.
  58.  
  59. RDCF is fully reentrant with respect to files on different drives. It is also
  60. reentrant with respect to files on the same drive, provided they are opened for
  61. reading only. It is not reentrant with respect to different files on the same
  62. drive, if any of them are being written. Therefore, access to it in this case
  63. must be serialized on a drive-by-drive basis when it is used in a multitasking
  64. system.
  65.  
  66. RDCF does not call on the memory allocator. All working storage for an open
  67. file is contained in a file control block and a scratch buffer that you must
  68. allocate in some manner before calling on RDCF. In a manner of speaking, this
  69. is a reversion to the old CP/M standard, but it permits complete reentrancy
  70. and does not limit the number of open files.
  71.  
  72. Since RDCF treats each open file as though it were the only open file, it
  73. cannot detect collisions. For example, in a multitasking system, if a file is
  74. written by two tasks at the same time, it will be corrupted. The disk may end
  75. up with lost clusters and cross-linked chains, but other files on the same disk
  76. should keep their integrity.
  77.  
  78. RDCF requires access to a real-time clock.  If your system does not have a
  79. real-time clock, you can write a dummy clock interface that always returns some
  80. standard date and time, such as the notorious 1/1/80 00:00:00, which will be
  81. applied whenever a file is created or modified.
  82.  
  83. RDCF accesses a disk one sector at a time. While this may seem appallingly
  84. inefficient, it appears adequate in some cases where only minimal file
  85. operations are required. A simple cache system, which is also available from
  86. the same source, will improve its efficiency in other cases. With simple
  87. interfaces and full source code, you can make other changes that you deem
  88. necessary for your own application.
  89.  
  90. RDCF can be compiled as a read-only file system. This eliminates much of the
  91. code and is suitable for devices that load operating code and other data from
  92. DOS diskettes but do not write anything on them.
  93.  
  94. RDCF can be compiled to handle multiple drives, in which case every file
  95. specification must begin with a drive letter (followed by a colon).  If your
  96. system has only one drive, or if you prefer to handle drive selection outside
  97. RDCF, you can compile RDCF without multiple drives, in which case a file
  98. specification must NOT begin with a drive letter.
  99.  
  100. The interface to RDCF is not ANSI-compliant, although you could put an ANSI
  101. compliant interface on top of it.
  102.  
  103.  
  104. 2. Compilation Instructions
  105. ---------------------------
  106.  
  107. The source code for RDCF 2.0 consists of the files RDCF2.C and RDCF2.H. The
  108. header file RDCF2.H should be #included in any source file that calls on the
  109. RDCF, because it contains function prototypes and other necessary definitions.
  110.  
  111. Since a DOS diskette contains a number of fields of specific sizes, your C
  112. compiler must have types of the same sizes. Here is what is required:
  113.  
  114.      type   number of bits
  115.      -----  --------------
  116.      char         8
  117.      short       16
  118.      long        32
  119.      int     at least 16
  120.  
  121. If your application is to run on a CPU with "big endian" byte ordering, such as
  122. one of the Motorola 68000 series, RDCF will have to do some byte swapping
  123. because DOS diskettes contain fields with "little endian" ordering. You can do
  124. this by #defining the variable _BIG_ENDIAN.
  125.  
  126. If you do not need to write anything on disk, you can save a great deal of code
  127. by #defining the variable RDCF_SYSTEM_READ_ONLY. This eliminates almost all
  128. code devoted to writing.
  129.  
  130. If you system has multiple drives, you can #define the variable
  131. RDCF_MULTIPLE_DRIVES.  In this case RDCF will require each file specification
  132. to begin with a drive letter (followed by a colon), and it will pass the drive
  133. number to the drive interface.
  134.  
  135. If your application has only one drive, or if it has more than one drive but
  136. you want to handle drive selection outside RDCF, leave the variable
  137. RDCF_MULTIPLE_DRIVES undefined.  In this case a file specification passed to
  138. RDCF must NOT begin with a drive letter.
  139.  
  140. All DOS diskettes (and nearly all DOS hard disks) use 512-byte sectors, so the
  141. following definition is included in the header file RDCF2.H:
  142.  
  143.      #define RDCF_SECTOR_SIZE 512
  144.  
  145. If you change this value, RDCF won't be compatible with DOS, but it can operate
  146. in a consistent manner on disks that it has formatted.
  147.  
  148. If you leave RDCF_SECTOR_SIZE undefined, then RDCF will read the sector size
  149. from the bootstrap sector of each disk.  This produces less efficient code,
  150. because expressions involving the sector size cannot be evaluated at compile
  151. time.  However, it enables RDCF to adapt itself to different sector sizes at
  152. run time.
  153.  
  154. You can cut out the code for any RDCF function that you don't need. The
  155. publicly defined functions in RDCF2.C do not call each other, so one or more
  156. may be removed without difficulty. For example, if you do only sequential file
  157. access, you can cut out the function rdcf_seek(). In fact, RDCF probably has
  158. more functions than most applications require.
  159.  
  160. RDCF calls on the following standard C functions and macros, which are widely
  161. available and are usually reentrant:
  162.  
  163.      isalpha() longjmp() memcmp() memcpy() memset() setjmp() toupper()
  164.  
  165. RDCF presumes that all file specifications are expressed in ASCII and that the
  166. C compiler uses ASCII for characters and strings.
  167.  
  168. To prevent identifier conflicts, all publicly defined RDCF labels begin with
  169. the characters "RDCF", "_RDCF" or "rdcf".
  170.  
  171. The following public domain packages are usually distributed along with RDCF
  172. 2.0:
  173.  
  174.      package    files
  175.      ---------  -----------------------------
  176.      CACHE 1.1  CACHE.C, CACHE.DOC, CACHE.H
  177.      FILES      FILES.C, FILES.COM, FILES.DOC
  178.  
  179. The FILES package contains examples of the use of RDCF. It is also a rather
  180. handy diskette utility.
  181.  
  182.  
  183. 3. Drive Access
  184. ---------------
  185.  
  186. RDCF does not read or write disks directly. You must supply it with a pointer
  187. to a function that you have written or adapted for this purpose. RDCF then
  188. calls this function whenever it needs to read or write a disk sector. The
  189. format of the function call is as follows:
  190.  
  191.      e = (*drive_access)(write, drive, LSN, buffer);
  192.  
  193.      int write;       nonzero (true) for a write operation; zero (false)
  194.                       for a read operation
  195.  
  196.      unsigned drive;  drive (0=A, 1=B, etc)
  197.  
  198.      unsigned LSN;    logical sector number
  199.  
  200.      void *buffer;    memory buffer for data
  201.  
  202.      unsigned e;      0 for a successful read or write, or an
  203.                       implementation-defined nonzero error code
  204.  
  205. The function is called to read or write only one sector at a time. However,
  206. you may want to implement some kind of read-ahead, caching or delayed writing
  207. at a lower level to improve efficiency.
  208.  
  209. The function may be required to convert the LSN into side, track and sector
  210. numbers, although many disk controllers will make the conversion internally.
  211. The layout of LSN's is fairly standard, and is designed to minimize head
  212. motion when LSN's are accessed in ascending numerical order. On DOS systems,
  213. the conversion is made as follows:
  214.  
  215.      sector number = LSN % (number of sectors per track) + 1
  216.  
  217.      side number = (LSN / (number of sectors per track)) % (number of sides)
  218.  
  219.      track number = LSN / ((number of sectors per track) * (number of sides))
  220.  
  221. The sector size, the number of sectors per track and the number of sides are
  222. written into the following bytes of LSN 0 (where byte 0 is the first byte):
  223.  
  224.      byte  contents
  225.      ----  --------------------------------------
  226.       11   LS byte of number of bytes per sector
  227.       12   MS byte of number of bytes per sector
  228.       24   LS byte of number of sectors per track
  229.       25   MS byte of number of sectors per track
  230.       26   LS byte of number of sides
  231.       27   MS byte of number of sides
  232.  
  233. If RDCF is to adapt automatically to diskettes of different formats in the same
  234. drive, the function (*drive_access)() can simply record these values whenever
  235. LSN 0 is read or written and then use them to find other sectors. Notice that
  236. LSN 0 is always sector 1 of track 0 on side 0.
  237.  
  238. An error code must be a 16-bit nonzero unsigned value. Its format is
  239. implementation-dependent. When RDCF receives a nonzero return value from the
  240. function (*drive_access)(), it aborts the current operation, puts the return
  241. value into the file control block member called "drive_error" and returns the
  242. error code RDCF_DRIVE_ERROR.
  243.  
  244. Error correction and retries, if any, must be implemented at a lower level.
  245.  
  246. If RDCF is used in a reentrant fashion, the function (*drive_access)() must
  247. also have the required reentrancy.
  248.  
  249. Here is a drive access function that can be used with Turbo C 2.0 (or a
  250. compatible later version of Borland or Turbo C++) under DOS:
  251.  
  252.      #include <dos.h>
  253.  
  254.      unsigned drive_access(int write, unsigned drive, unsigned LSN,
  255.        void *buffer)
  256.      {
  257.        _SI; _DI;
  258.        return write ? abswrite(drive, 1, LSN, buffer) :
  259.          absread(drive, 1, LSN, buffer);
  260.      }
  261.  
  262. The strange-looking first line of the function goads the compiler into saving
  263. and restoring the SI and DI registers, something that absread() and abswrite()
  264. should do but don't always do, especially when a drive error is detected.
  265.  
  266. DOS does a little bit of caching when you access disks in this manner.
  267. Therefore, you should call bdos(13,0,0) to flush the buffers before returning
  268. control to DOS.  Otherwise DOS may not recognize the changes RDCF has made.
  269.  
  270.  
  271. 4. Real Time Clock Access
  272. -------------------------
  273.  
  274. When RDCF needs the date and time, it calls a function as follows:
  275.  
  276.      rdcf_get_date_and_time(p);
  277.  
  278.      struct rdcf_date_and_time *p;  pointer to structure to receive
  279.                                     date and time
  280.  
  281. You must write a version of rdcf_date_and_time() for your own system.  If your
  282. system has no real-time clock, the following function will supply the notorious
  283. 1-1-80 00:00:00 as the current date and time:
  284.  
  285.      struct rdcf_date_and_time(struct rdcf_date_and_time *p)
  286.      {
  287.        static struct rdcf_date_and_time DT = {0,0,0,1,1,1980};
  288.        memcpy(p, &DT, sizeof(DT));
  289.      }
  290.  
  291. If you run RDCF under DOS and use Turbo C 2.0 (or a compatible later version of
  292. Turbo or Borland C++), the following function will supply the date and time
  293. taken from the system clock:
  294.  
  295.      void rdcf_get_date_and_time(struct rdcf_date_and_time *p)
  296.      {
  297.        struct date d;
  298.        struct time t;
  299.        int day;
  300.        getdate(&d);
  301.        day = d.da_day;
  302.        gettime(&t);
  303.        getdate(&d);
  304.        if (day != d.da_day) gettime(&t);
  305.        p->month = d.da_mon;
  306.        p->day = d.da_day;
  307.        p->year = d.da_year;
  308.        p->hour = t.ti_hour;
  309.        p->minute = t.ti_min;
  310.        p->second = t.ti_sec;
  311.      }
  312.  
  313. Notice that it is sometimes necessary to read the date and time twice to be
  314. sure of getting a consistent reading when the function is called at midnight.
  315.  
  316. DOS files always have dates in the period 1980-2107.
  317.  
  318.  
  319. 5. The File Control Block
  320. -------------------------
  321.  
  322. All working storage for an open file is contained in a file control block of
  323. type "struct rdcf", which is defined in the header file RDCF2.H, and a scratch
  324. buffer described below.  You must allocate space for file control blocks and
  325. scratch buffers before calling on RDCF, since RDCF itself does not call on the
  326. memory allocator.
  327.  
  328. The first element of a file control block is a pointer to a scratch buffer
  329. with room for RDCF_SECTOR_SIZE unsigned characters. The second element is a
  330. pointer to the drive access function defined above. You must initialize these
  331. pointers, perhaps as follows:
  332.  
  333.         static unsigned char my_buffer[RDCF_SECTOR_SIZE];
  334.         static struct rdcf f = {my_buffer, drive_access};
  335.  
  336. If your implementation has a memory allocator, you can use that instead:
  337.  
  338.         struct rcdf f;
  339.         f.buffer = malloc(RDCF_SECTOR_SIZE);
  340.         f.drive_access = drive_access;
  341.  
  342. If you leave RDCF_SECTOR_SIZE undefined because your system uses different
  343. sector sizes on different disks, the buffer must be large enough to hold the
  344. largest sector.
  345.  
  346. If RDCF_MULTIPLE_DRIVES is undefined, but your system has more than one drive,
  347. you must also put the appropriate drive number into the member f.drive so that
  348. it can be passed to the drive access function. 
  349.  
  350. With one exception involving the function rdcf_next_file_information(), neither
  351. the scratch buffer contents nor the scratch buffer pointer needs to be
  352. maintained from one call on RDCF to the next.  However, if RDCF is to be used
  353. in a multitasking system, tasks that can call RDCF in a reentrant fashion must
  354. use different scratch buffers. In most cases, it is sufficient to allocate one
  355. scratch buffer for each drive, and to serialize calls on RDCF for each drive.
  356.  
  357. The drive access function pointer must not be changed while the file
  358. corresponding to the file control block is open.
  359.  
  360. You don't have to perform any other initialization on your file control
  361. blocks; RDCF does that for you.
  362.  
  363. The file control block for a successfully opened file contains a number of
  364. members that you can (safely) read and/or write directly, without calling on
  365. RDCF:
  366.  
  367.      member           permitted
  368.                        access     meaning
  369.      ---------------  ----------  ----------------------------------------
  370.      buffer           read/write  pointer to scratch buffer
  371.      drive_access     read/write  pointer to drive access function
  372.      drive            read/write  drive (0=A, 1=B, etc.)
  373.      file               read      file information block, described below
  374.      position           read      file pointer
  375.      drive_error        read      error when RDCF_DRIVE_ERROR is returned
  376.      result             read      result returned by most recent operation
  377.  
  378. Of course, you should write into the "drive" member only if you have left
  379. RDCF_MULTIPLE_DRIVES undefined but your system has more than one drive.
  380.  
  381. The file information block is described more fully in Section 6 below.
  382.  
  383. File control blocks of the same format are also used by some RDCF functions for
  384. working storage, although nothing more than result codes are returned in them.
  385.  
  386.  
  387. 6. The File Information Block
  388. -----------------------------
  389.  
  390. The "file" member of a file control block, when filled by RDCF, contains the
  391. following information about a file:
  392.  
  393.      member         meaning
  394.      ---------      ---------------------------------------------------
  395.      spec[13]       name and extension in ASCII, terminated by \0
  396.      attribute      DOS file attribute byte (see below)
  397.      date_and_time  file date and time
  398.      first_cluster  number of first cluster
  399.      size           file length in bytes (0 for volume or subdirectory)
  400.  
  401. The name and extension are at most eight and three characters long,
  402. respectively, they are separated by a period (.) if the extension is
  403. non-blank, and they are terminated by a nul (\0).  RDCF always converts small
  404. letters in file names and extensions to the corresponding capital letters
  405. before putting them into the file information block.
  406.  
  407. If the information block represents a volume name, however, then the spec[]
  408. member contains the name, which is eleven characters long and may contain
  409. small letters and special characters.
  410.  
  411. The date_and_time member is itself a structure with the following members:
  412.  
  413.      member  meaning    range
  414.      ------  ---------  -----------------
  415.      second  file time  0-58, always even
  416.      minute  file time  0-59
  417.      hour    file time  0-23
  418.      day     file date  1-31
  419.      month   file date  1-12
  420.      year    file date  1980-2107
  421.  
  422. The bits of the attribute byte are represented by mnemonics defined in RDCF2.H:
  423.  
  424.     #define RDCF_READ_ONLY  0x01
  425.     #define RDCF_HIDDEN     0x02
  426.     #define RDCF_SYSTEM     0x04
  427.     #define RDCF_VOLUME     0x08
  428.     #define RDCF_DIRECTORY  0x10
  429.     #define RDCF_ARCHIVE    0x20
  430.  
  431. The file information and date-and-time blocks also appear outside the file
  432. control block in some contexts.
  433.  
  434.  
  435. 7. RDCF File Specifications
  436. ---------------------------
  437.  
  438. A file specification under RDCF is almost the same as its DOS counterpart.
  439.  
  440. As in DOS, case is not significant in file specifications.  Moreover, every
  441. name is truncated to eight characters, and every extension is truncated to
  442. three characters.  Hence "A:MYPROGRAM.PASCAL", "A:MYPROGRA.PAS", and
  443. "a:myprogra.pas" all represent the same file.
  444.  
  445. In a multiple-drive system, the file specification MUST begin with a drive
  446. specification (a drive letter followed by a colon). In systems with only one
  447. drive, the file specification must NOT begin with a drive letter.  If you want
  448. to handle drive selection outside RDCF, adjust the drive access pointer and
  449. the drive number in the file control block to select the desired drive, and
  450. then remove the drive letter and colon from the file specification before
  451. calling on RDCF.
  452.  
  453. Since there is no "current directory", the file specification must begin at the
  454. root and contain the names of all intermediate subdirectories.  The backslash
  455. at the beginning of the directory path is superfluous and is NOT used.  Hence
  456. a file specification such as "C:\UTIL\CHKDSK.COM", which is quite familiar
  457. under DOS, is invalid under RDCF.  The RDCF specification is
  458. "C:UTIL\CHKDSK.COM".
  459.  
  460. For the same reason, RDCF does not permit the special subdirectories "." and
  461. ".." in a directory path, but to maintain disk-level compatibility with DOS, it
  462. puts them into subdirectories that it creates.
  463.  
  464. A directory specification is the same as a file specification, except that it
  465. refers to a subdirectory.
  466.  
  467. Where required, a root directory is represented by a drive specification alone;
  468. e.g., "B:" represents the root directory on drive B:.  In single-drive systems,
  469. the empty string "" represents the root directory.
  470.  
  471. RDCF treats all file and drive specifications supplied to it as read-only
  472. strings.  They may reside in ROM.
  473.  
  474.  
  475. 8. The Program Interface
  476. ------------------------
  477.  
  478. The RDCF program interface consists of the following functions:
  479.  
  480.      function                     description
  481.      ---------------------------  -------------------------------------
  482.      rdcf_attribute()             change a file attribute
  483.      rdcf_close()                 close a file
  484.      rdcf_date_and_time()         change a file, volume or subdirectory
  485.                                     date and time
  486.      rdcf_delete()                delete a file, volume name or
  487.                                     subdirectory
  488.      rdcf_directory()             create a subdirectory
  489.      rdcf_format()                format a disk
  490.      rdcf_free_space()            get disk free space
  491.      rdcf_get_file_information()  get a directory entry
  492.      rdcf_get_volume()            get volume name
  493.      rdcf_match()                 match name and extension
  494.      rdcf_move()                  move a file or subdirectory
  495.      rdcf_next_file_information() get next directory entry
  496.      rdcf_open()                  open a file
  497.      rdcf_read()                  read from a file
  498.      rdcf_recover()               recover erased data
  499.      rdcf_rename()                rename a file or directory
  500.      rdcf_seek()                  move a file pointer
  501.      rdcf_set_file_information()  write into a directory entry
  502.      rdcf_set_volume()            write volume name
  503.      rdcf_sort_directory()        sort a directory
  504.      rdcf_undelete()              restore a deleted file
  505.      rdcf_wipe_drive()            wipe out erased data
  506.      rdcf_write()                 write into a file
  507.  
  508. There are also four externally defined variables, which for reentrancy must be
  509. considered read-only:
  510.  
  511.      rdcf_format_360    rdcf_format_1200
  512.      rdcf_format_720    rdcf_format_1440
  513.  
  514.  
  515. 8.1. rdcf_attribute() - Change a File Attribute
  516. -----------------------------------------------
  517.  
  518. The following function call changes a file's attribute byte:
  519.  
  520.      e = rdcf_attribute(fcb, filespec, attribute);
  521.  
  522.      struct rdcf *fcb;            pointer to file control block
  523.  
  524.      char *filespec;              file specification string, with
  525.                                   terminating \0
  526.  
  527.      unsigned attribute;          new attribute byte
  528.  
  529.      int e;                       0 if file was successfully modified,
  530.                                   or negative error code
  531.  
  532. Only the following attribute bits are affected by this function:
  533.  
  534.      RDCF_ARCHIVE     RDCF_READ_ONLY
  535.      RDCF_HIDDEN      RDCF_SYSTEM
  536.  
  537. Possible return values are as follows:
  538.  
  539.      return value             meaning
  540.      -----------------------  -------------------------------------
  541.      0                        successful operation
  542.      RDCF_DIRECTORY_CONFLICT  file name conflicts with subdirectory
  543.      RDCF_DISK_FORMAT_ERROR   disk improperly formatted
  544.      RDCF_DRIVE_ERROR         error in reading or writing disk
  545.      RDCF_FILE_FORMAT_ERROR   corrupt file allocation table
  546.      RDCF_FILE_NOT_FOUND      file not found
  547.      RDCF_INVALID_SPEC        invalid drive or file specification
  548.      RDCF_INVALID_DIRECTORY   nonexistent subdirectory in path
  549.  
  550. If RDCF is compiled as a read-only file system, this function is not defined.
  551.  
  552.  
  553. 8.2. rdcf_close() - Close a File
  554. --------------------------------
  555.  
  556. If a file has been written or otherwise modified, you must close it in order to
  557. update its directory entry. Here is the appropriate function call:
  558.  
  559.      e = rdcf_close(fcb);
  560.  
  561.      struct rdcf *fcb;     pointer to open file control block
  562.  
  563.      int e;                0 for a successful operation, or a negative error
  564.                            code
  565.  
  566. The file control block must have been successfully opened by rdcf_open().
  567.  
  568. If the file has been modified, its date and time will be set to the value
  569. returned by rdcf_get_date_and_time().
  570.  
  571. If a file has not been written or otherwise modified, there is no need to close
  572. it, and this function will do nothing to it. If RDCF is compiled as a read-only
  573. file system, this function is not even defined.
  574.  
  575. Possible return values are as follows:
  576.  
  577.      return value            meaning
  578.      -----------------       --------------------------------
  579.      0                       successful operation
  580.      RDCF_DISK_FORMAT_ERROR  disk improperly formatted
  581.      RDCF_DRIVE_ERROR        error in reading or writing disk
  582.  
  583.  
  584. 8.3. rdcf_date_and_time() - Change Date and Time
  585. ------------------------------------------------
  586.  
  587. The following function call changes the date and time of a file, volume name
  588. or subdirectory:
  589.  
  590.      e = rdcf_date_and_time(fcb, filespec, t);
  591.  
  592.      struct rdcf *fcb;             pointer to file control block
  593.  
  594.      char *filespec;               file specification string, with
  595.                                    terminating \0
  596.  
  597.      struct rdcf_date_and_time *t; pointer to block containing desired
  598.                                    date and time
  599.  
  600.      int e;                        0 if operation was successful,
  601.                                    or negative error code
  602.  
  603. If RDCF_MULTIPLE_DRIVE is defined, the file specification for a volume name
  604. consists of a drive specification alone, e.g., "A:" for drive A:, "B:" for
  605. drive B:, etc.  In other cases, the file specification for a volume name is
  606. the empty string ("").
  607.  
  608. When the time and date of a subdirectory are changed, the time and date of its
  609. special subdirectories "." and ".." are also changed.
  610.  
  611. Possible return values are as follows:
  612.  
  613.      return value             meaning
  614.      -----------------------  ----------------------------------
  615.      0                        successful operation
  616.      RDCF_DISK_FORMAT_ERROR   disk improperly formatted
  617.      RDCF_DRIVE_ERROR         error in reading or writing disk
  618.      RDCF_FILE_FORMAT_ERROR   corrupt file allocation table
  619.      RDCF_FILE_NOT_FOUND      file not found
  620.      RDCF_INVALID_SPEC        invalid drive or file specification
  621.      RDCF_INVALID_DIRECTORY   nonexistent subdirectory in path
  622.  
  623. If RDCF is compiled as a read-only file system, this function is not defined.
  624.  
  625.  
  626. 8.4. rdcf_delete() - Delete a File, Volume Name or Subdirectory
  627. ----------------------------------------------------------------
  628.  
  629. The following function call deletes a file, volume name or subdirectory:
  630.  
  631.      e = rdcf_delete(fcb, filespec);
  632.  
  633.      struct rdcf *fcb;            pointer to file control block
  634.  
  635.      char *filespec;              file specification string, with
  636.                                   terminating \0
  637.  
  638.      int e;                       0 if file was successfully opened,
  639.                                   or negative error code
  640.  
  641. If RDCF_MULTIPLE_DRIVE is defined, the file specification for a volume name
  642. consists of a drive specification alone, e.g., "A:" for drive A:, "B:" for
  643. drive B:, etc.  In other cases, the file specification for a volume name is
  644. the empty string ("").
  645.  
  646. Possible return values are as follows:
  647.  
  648.      return value             meaning
  649.      -----------------------  ----------------------------------------
  650.      0                        successful operation
  651.      RDCF_ACCESS_DENIED       attempt to delete a read-only file or a
  652.                                 subdirectory that is not empty
  653.      RDCF_DISK_FORMAT_ERROR   disk improperly formatted
  654.      RDCF_DRIVE_ERROR         error in reading or writing disk
  655.      RDCF_FILE_NOT_FOUND      file, volume name or directory not found
  656.      RDCF_INVALID_SPEC        invalid drive or file specification
  657.      RDCF_INVALID_DIRECTORY   nonexistent subdirectory in path
  658.  
  659. If RDCF is compiled as a read-only file system, this function is not defined.
  660.  
  661.  
  662. 8.5. rdcf_directory() - Create a New Subdirectory
  663. -------------------------------------------------
  664.  
  665. The following function call creates a new subdirectory:
  666.  
  667.      e = rdcf_directory(fcb, filespec);
  668.  
  669.      struct rdcf *fcb;             pointer to file control block
  670.  
  671.      char *filespec;               file specification string, with
  672.                                    terminating \0
  673.  
  674.      int e;                        0 if operation was successful,
  675.                                    or negative error code
  676.  
  677. The new directory, and its special subdirectories "." and "..", will bear the
  678. current date and time as determined by a call on rdcf_get_date_and_time().
  679.  
  680. Possible return values are as follows:
  681.  
  682.      return value             meaning
  683.      -----------------------  ----------------------------------------
  684.      0                        successful operation
  685.      RDCF_DIRECTORY_CONFLICT  name conflicts with file or subdirectory
  686.      RDCF_DIRECTORY_FULL      insufficient directory or data space
  687.      RDCF_DISK_FORMAT_ERROR   disk improperly formatted
  688.      RDCF_DRIVE_ERROR         error in reading or writing disk
  689.      RDCF_INVALID_SPEC        invalid drive or file specification
  690.      RDCF_INVALID_DIRECTORY   nonexistent subdirectory in path
  691.  
  692. If RDCF is compiled as a read-only file system, this function is not defined.
  693.  
  694.  
  695. 8.6. rdcf_format() - Format a Disk
  696. ----------------------------------
  697.  
  698. Formatting a disk usually involves two operations, both of which are performed
  699. by most DOS formatting utilities for diskettes.
  700.  
  701. The first operation, called physical formatting, divides the tracks up into
  702. sectors and writes the necessary sector numbers into them. The sectors are
  703. filled with meaningless bytes. RDCF has no provision for physical formatting
  704. because the procedure is highly hardware-dependent.
  705.  
  706. The second operation, called logical formatting, writes the required
  707. information into the bootstrap sector, the file allocation table, and the root
  708. directory. RDCF performs logical formatting with the following function call:
  709.  
  710.      e = rdcf_format(fcb, spec, format);
  711.  
  712.      struct rdcf *fcb;            pointer to file control block
  713.  
  714.      char *spec;                  drive specification ("A:", "B:", etc.),
  715.                                   omitted if RDCF_MULTIPLE_DRIVE is undefined
  716.  
  717.      struct rdcf_format *format;  pointer to descriptor block for desired
  718.                                   format
  719.  
  720.      int e;                       0 if operation was successful,
  721.                                   or negative error code
  722.  
  723. The format parameter has any of four values, depending on the type of disk
  724. being formatted:
  725.  
  726.      value of format    physical size  density  capacity
  727.      -----------------  -------------  -------  --------
  728.      &rdcf_format_360     5-1/4 inch   double   360K
  729.      &rdcf_format_720     3-1/2 inch   double   720K
  730.      &rdcf_format_1200    5-1/4 inch    high    1.2M
  731.      &rdcf_format_1440    3-1/2 inch    high    1.44M
  732.  
  733. Logical formatting deletes all files, subdirectories and the volume name. Some
  734. of this information can be reconstructed by rdcf_recover() or by special
  735. recovery programs if it has not been overwritten. However, all the information
  736. becomes inaccessible through normal DOS and RDCF calls. The disk also becomes
  737. unbootable and cannot be made bootable with the DOS SYS utility.
  738.  
  739. This function is especially useful if the data storage device is not a
  740. DOS-compatible disk. You can use it to format a RAM disk, a portion of a hard
  741. disk, or even a file and use it as though it were a disk.  The function
  742. (*drive_access)() usually needs to be modified, but no other changes are
  743. required.
  744.  
  745. If you want to use a nonstandard format, you can make up your own format
  746. descriptor block.  Here is what is in it:
  747.  
  748.      byte  contents
  749.      ----  ------------------------------------------------------
  750.       0    LS byte of number of bytes per sector
  751.       1    MS byte of number of bytes per sector
  752.       2    number of sectors per data cluster
  753.       3    1
  754.       4    0
  755.       5    number of file allocation tables
  756.       6    LS byte of number of root directory entries
  757.       7    MS byte of number of root directory entries
  758.       8    LS byte of total number of sectors
  759.       9    MS byte of total number of sectors
  760.      10    unused
  761.      11    LS byte of number of sectors per file allocation table
  762.      12    MS byte of number of sectors per file allocation table
  763.      13    LS byte of number of sectors per track
  764.      14    MS byte of number of sectors per track
  765.      15    LS byte of number of sides
  766.      16    MS byte of number of sides
  767.      17    unused
  768.      18    unused
  769.  
  770. NOTICE that some two-byte parameters are not aligned on even boundaries.
  771.  
  772. Of course, if you format a disk in a nonstandard manner, DOS may not be able to
  773. read it.  There are a number of limitations on the parameters to guarantee a
  774. self-consistent format that RDCF can use:
  775.  
  776.      (1) None of the parameters can be zero (although the MS byte of a two-byte
  777.          parameter can be zero).
  778.  
  779.      (2) The sector size must be a multiple of 32; but if RDCF_SECTOR_SIZE is
  780.          defined, RDCF ignores this field.
  781.  
  782.      (3) The number of root directory entries must be a multiple of the number
  783.          of entries in a sector.  Each entry occupies 32 bytes, so if 512-byte
  784.          sectors are used, the number of entries per sector is 16.
  785.  
  786.      (4) The disk contains the following areas, which must add up to the
  787.          specified total number of sectors:
  788.  
  789.           (a) one bootstrap sector,
  790.  
  791.           (b) the specified number of file allocation tables, each containing
  792.               the specified number of sectors,
  793.  
  794.           (c) the root directory, and
  795.  
  796.           (d) the data sectors.
  797.  
  798.      (5) The number of data sectors must be a multiple of the number of sectors
  799.          per data cluster.  Their quotient is the number of data clusters.
  800.  
  801.      (6) The number of data clusters must not exceed 65,517.
  802.  
  803.      (6) If the number of data clusters is 4077 or less, then each file
  804.          allocation table must contain at least 3 bytes plus one and one-half
  805.          bytes for each data cluster.  Otherwise, each file allocation table
  806.          must contain at least 4 bytes plus 2 bytes for each data cluster.
  807.  
  808. Parameters described as "unused" are not used by RDCF, although they may have
  809. meanings on a DOS diskette.  The rdcf_format() function makes only a
  810. perfunctory consistency check on the parameters.
  811.  
  812. RDCF does not use the number of sectors per track or the number of sides, but
  813. the function (*drive_access)() may need them.
  814.  
  815. Possible return values are as follows:
  816.  
  817.      return value               meaning
  818.      ------------------------   -----------------------------
  819.      0                          successful operation
  820.      RDCF_DISK_FORMAT_ERROR     improper format control block
  821.      RDCF_DRIVE_ERROR           error in writing disk
  822.      RDCF_INVALID_SPEC          invalid drive specification
  823.  
  824. If RDCF is compiled as a read-only file system, this function is not defined.
  825.  
  826.  
  827. 8.7. rdcf_free_space() -  Get Disk Free Space
  828. ---------------------------------------------
  829.  
  830. The following function call returns the number of bytes of free space on a
  831. disk:
  832.  
  833.      n = rdcf_free_space(fcb, char *spec);
  834.  
  835.      struct rdcf *fcb;            pointer to file control block
  836.  
  837.      char *spec;                  drive specification ("A:", "B:", etc.),
  838.                                   omitted if RDCF_MULTIPLE_DRIVE is undefined
  839.  
  840.      long n;                      number of free bytes, or a
  841.                                   negative error code
  842.  
  843. If the operation is successful, the number of free bytes is also left in the
  844. member fcb->file.size.
  845.  
  846. In the absence of drive errors, the number of free bytes returned by this
  847. function is the maximum number of bytes that can be added to an existing file
  848. that fills a whole number of data clusters. The number of additional bytes
  849. that can be written to existing files may be larger, because each file may
  850. have some empty space in its last cluster that is not counted as free by this
  851. function.
  852.  
  853. The number of bytes that can be written to a newly created file is also the
  854. same as the value returned by this function, except in one peculiar case.  If
  855. a new file is added to a subdirectory, it may be necessary to add a cluster to
  856. the subdirectory to accommodate the new file entry.  This cluster is not
  857. available for file data.
  858.  
  859. Possible error codes are as follows:
  860.  
  861.      return value            meaning
  862.      ----------------------  ---------------------------
  863.      RDCF_DISK_FORMAT_ERROR  disk improperly formatted
  864.      RDCF_DRIVE_ERROR        error in reading disk
  865.      RDCF_INVALID_SPEC       invalid drive specification
  866.  
  867.  
  868. 8.8. rdcf_get_file_information() - Get a Directory Entry
  869. --------------------------------------------------------
  870.  
  871. The following function reads a directory entry:
  872.  
  873.      e = rdcf_get_file_information(fcb, specs, index);
  874.  
  875.      struct rdcf *fcb;            pointer to file control block
  876.  
  877.      char *filespec;              directory specification string, with
  878.                                   terminating \0
  879.  
  880.      unsigned index;              index of desired entry (0 = first entry,
  881.                                   1 = second entry, etc.)
  882.  
  883.      int e;                       0 if entry was successfully read,
  884.                                   or negative error code
  885.  
  886. If RDCF_MULTIPLE_DRIVE is defined, the directory specification string for the
  887. root directory consists of a drive specification alone, such as "D:".
  888. Otherwise, the empty string ("") represents the root directory.
  889.  
  890. If the operation is successful, useful information about the file, volume name
  891. or subdirectory will be found in the file information block fcb->file.
  892.  
  893. If the return value is RDCF_FILE_NOT_FOUND, the entry represents an erased
  894. file, volume name or subdirectory.  The first character in the name is invalid
  895. but other information is valid and reflects the status of the file, volume
  896. name or subdirectory before it was deleted.
  897.  
  898. If the entry represents a volume name or subdirectory, the RDCF_VOLUME or
  899. RDCF_DIRECTORY bit will be set in the attribute byte.
  900.  
  901. Entries 0 and 1 in a subdirectory represent the special directory entries named
  902. "." and "..".  RDCF makes no use of these special entries, but it faithfully
  903. emulates this DOS feature.
  904.  
  905. The value RDCF_DIRECTORY_FULL is returned if the index would put the entry
  906. beyond the end of the directory area, or if the entry lies inside this area but
  907. has never been used since the directory was created. In either case, the entry
  908. is invalid and there are no valid entries with any higher index value.
  909.  
  910. Even if the entry is valid and represents a file, the file control block may
  911. not be used to read, write or otherwise manipulate the file until it is
  912. successfully opened by rdcf_open().
  913.  
  914. If you call this function repeatedly to scan the directory, you should
  915. probably use some kind of caching. Otherwise, both the bootstrap block and the
  916. directory will be read from disk with each function call. Even without
  917. caching, this function produced acceptable results when used to display a
  918. directory listing of a floppy diskette, although the process was a little
  919. slower than most people would prefer.
  920.  
  921. The companion function rdcf_next_file_information(), which is described below,
  922. can also be called to obtain the following entry without repeating the entire
  923. directory search.
  924.  
  925. Possible return values are as follows:
  926.  
  927.      return value            meaning
  928.      ----------------------  ------------------------------
  929.      0                       successful operation
  930.      RDCF_DIRECTORY_FULL     index is past end of directory
  931.      RDCF_DISK_FORMAT_ERROR  disk improperly formatted
  932.      RDCF_DRIVE_ERROR        error in reading disk
  933.      RDCF_FILE_NOT_FOUND     entry represents deleted file
  934.      RDCF_INVALID_SPEC       invalid drive specification
  935.      RDCF_INVALID_DIRECTORY  nonexistent subdirectory in path
  936.  
  937.  
  938. 8.9. rdcf_get_volume() - Get Volume Name
  939. ----------------------------------------
  940.  
  941. The following function call scans the root directory for the volume name, if
  942. any:
  943.  
  944.      e = rdcf_get_volume(fcb, char *spec);
  945.  
  946.      struct rdcf *fcb;            pointer to file control block
  947.  
  948.      char *spec;                  drive specification ("A:", "B:", etc.),
  949.                                   omitted if RDCF_MULTIPLE_DRIVE is undefined
  950.  
  951.      int e;                       0 if volume name was successfully read,
  952.                                   or negative error code
  953.  
  954. If the operation is successful, information regarding the volume name is left
  955. in the file information block fcb->file.
  956.  
  957. Possible return values are as follows:
  958.  
  959.      return value            meaning
  960.      ----------------------  ------------------------------
  961.      0                       successful operation
  962.      RDCF_DISK_FORMAT_ERROR  disk improperly formatted
  963.      RDCF_DRIVE_ERROR        error in reading disk
  964.      RDCF_FILE_NOT_FOUND     disk has no volume name
  965.      RDCF_INVALID_SPEC       invalid drive specification
  966.  
  967.  
  968. 8.10. rdcf_next_file_information() - Get Next Directory Entry
  969. -------------------------------------------------------------
  970.  
  971. The following function reads the next directory entry after the one read by the
  972. most recent call on rdcf_get_file_information() or rdcf_next_file_information()
  973. using the same file control block:
  974.  
  975.      e = rdcf_next_file_information(fcb);
  976.  
  977.      struct rdcf *fcb;            pointer to the same file control block used
  978.                                   by a previous call on this function or
  979.                                   rdcf_get_file_information()
  980.  
  981.      int e;                       0 if entry was successfully read,
  982.                                   or negative error code
  983.  
  984. The file control block and scratch buffer must be the same ones used by the
  985. preceding call on rdcf_get_file_information() or this function, and the
  986. directory structure on the disk must not have changed.  The preceding call must
  987. not have returned RDCF_DIRECTORY_FULL.  This function uses information left in
  988. the file control block to find the next directory entry without rescanning the
  989. directory.
  990.  
  991. If the operation is successful, useful information about the file, volume name
  992. or subdirectory will be found in the file information block fcb->file.
  993.  
  994. If the return value is RDCF_FILE_NOT_FOUND, the entry represents an erased
  995. file, volume name or subdirectory.  The first character in the name is invalid
  996. but other information is valid and reflects the status of the file, volume
  997. name or subdirectory before it was deleted.
  998.  
  999. If the entry represents a volume name or subdirectory, the RDCF_VOLUME or
  1000. RDCF_DIRECTORY bit will be set in the attribute byte.
  1001.  
  1002. Entries 0 and 1 in a subdirectory represent the special directory entries named
  1003. "." and "..".  RDCF makes no use of these special entries, but it faithfully
  1004. emulates this DOS quirk.
  1005.  
  1006. The value RDCF_DIRECTORY_FULL is returned if the index would put the entry
  1007. beyond the end of the directory area, or if the entry lies inside this area but
  1008. has never been used since the directory was created. In either case, the entry
  1009. is invalid and there are no valid entries with any higher index value.
  1010.  
  1011. Even if the entry is valid and represents a file, the file control block may
  1012. not be used to read, write or otherwise manipulate the file until it is
  1013. successfully opened by rdcf_open().
  1014.  
  1015. Possible return values are as follows:
  1016.  
  1017.      return value            meaning
  1018.      ----------------------  ------------------------------
  1019.      0                       successful operation
  1020.      RDCF_DIRECTORY_FULL     index is past end of directory
  1021.      RDCF_DISK_FORMAT_ERROR  disk improperly formatted
  1022.      RDCF_DRIVE_ERROR        error in reading disk
  1023.      RDCF_FILE_NOT_FOUND     entry represents deleted file
  1024.  
  1025.  
  1026. 8.11. rdcf_match() - Match Name and Extension
  1027. ---------------------------------------------
  1028.  
  1029. The following function determines whether a DOS file name and extension match
  1030. a DOS pattern, which may include the special characters ? and *:
  1031.  
  1032.      match = rdcf_match(name_extension, pattern);
  1033.  
  1034.      char *name_extension;  DOS name and extension, with separating . and
  1035.                             terminating \0
  1036.  
  1037.      char *pattern;         DOS name and extension, with separating . and
  1038.                             terminating \0, possibly including the special
  1039.                             characters ? and *
  1040.  
  1041.      int match;             true (nonzero) if the name and extension match
  1042.                             the pattern; false (zero) otherwise
  1043.  
  1044. The function follows all the usual DOS quirks.  Small letters are converted to
  1045. capital letters before comparison.  The name is truncated to eight characters,
  1046. and the extension is truncated to three characters.
  1047.  
  1048. The function does not check the validity of the name and extension or the
  1049. pattern.
  1050.  
  1051.  
  1052. 8.12. rdcf_move() - Move a File or Subdirectory
  1053. -----------------------------------------------
  1054.  
  1055. The following function call moves a file or subdirectory from one directory to
  1056. another ON THE SAME DRIVE:
  1057.  
  1058.      e = rdcf_move(fcb, old_filespec, new_filespec);
  1059.  
  1060.      struct rdcf *fcb;            pointer to file control block
  1061.  
  1062.      char *old_filespec;          old file specification string, with
  1063.                                   terminating \0
  1064.  
  1065.      char *new_filespec;          new file specification, with
  1066.                                   terminating \0
  1067.  
  1068.      int e;                       0 if file was successfully opened,
  1069.                                   or negative error code
  1070.  
  1071. The new file specification may not begin with a drive specification, even if
  1072. RDCF_MULTIPLE_DRIVE is defined.  However, it may, and often does, begin with a
  1073. directory path.
  1074.  
  1075. The file name and extension in the new file specification need not be the same
  1076. as those in the old file specification.  The file or subdirectory can be
  1077. renamed as it is moved.
  1078.  
  1079. The file or directory entry in the old position will be marked as deleted.
  1080.  
  1081. You may use this function to move a subdirectory, but you must be careful not
  1082. to corrupt the tree structure by moving a subdirectory into itself or one of
  1083. its subdirectories.  RDCF will not protect you from such folly.
  1084.  
  1085. Possible return values are as follows:
  1086.  
  1087.      return value             meaning
  1088.      -----------------------  ------------------------------------------
  1089.      0                        successful operation
  1090.      RDCF_DIRECTORY_FULL      insufficient directory space for new entry
  1091.      RDCF_DISK_FORMAT_ERROR   disk improperly formatted
  1092.      RDCF_DRIVE_ERROR         error in reading or writing disk
  1093.      RDCF_FILE_NOT_FOUND      file not found
  1094.      RDCF_INVALID_DIRECTORY   nonexistent subdirectory in path
  1095.      RDCF_INVALID_SPEC        invalid drive or file specification
  1096.      RDCF_RENAMING_ERROR      new file specification is already in use
  1097.  
  1098. If RDCF is compiled as a read-only file system, this function is not defined.
  1099.  
  1100.  
  1101. 8.13. rdcf_open() - Open a File
  1102. -------------------------------
  1103.  
  1104. The following function call opens a file:
  1105.  
  1106.      e = rdcf_open(fcb, filespec, mode);
  1107.  
  1108.      struct rdcf *fcb;            pointer to file control block
  1109.  
  1110.      char *filespec;              file specification string, with
  1111.                                   terminating \0
  1112.  
  1113.      unsigned mode;               file mode (not used if RDCF is read-only)
  1114.  
  1115.      int e;                       0 if file was successfully opened,
  1116.                                   or negative error code
  1117.  
  1118. If the file is successfully opened, the file pointer is set to the beginning
  1119. of the file and the file control block is initialized for use by other RDCF
  1120. operations on the file.  The file information block fcb->file then contains
  1121. meaningful information about the file.
  1122.  
  1123. The mode may be as follows:
  1124.  
  1125.      mode             operation
  1126.      ---------------  ------------------------------------------------
  1127.      RDCF_CREATE      create file for writing, deleting the file if it
  1128.                         already exists
  1129.      RDCF_READ        open file for reading only
  1130.      RDCF_READ_WRITE  open file for reading and writing
  1131.  
  1132. In read-only file systems, RDCF_READ is the only mode permitted, so the mode
  1133. parameter is absent.
  1134.  
  1135. You may wish to open a file in the RDCF_READ mode merely to obtain information
  1136. from its file control block.  Then you can abandon or re-use the file control
  1137. block; there is no need to close the file.
  1138.  
  1139. You can emulate the full panoply of DOS open() modes by calling this function
  1140. more than once.
  1141.  
  1142. Possible return values are as follows:
  1143.  
  1144.      return value             meaning
  1145.      -----------------------  ----------------------------------------------
  1146.      0                        successful operation
  1147.      RDCF_ACCESS_DENIED       attempt to write a read-only file
  1148.      RDCF_DIRECTORY_CONFLICT  file name conflicts with subdirectory
  1149.      RDCF_DIRECTORY_FULL      insufficient directory space to create a file
  1150.      RDCF_DISK_FORMAT_ERROR   disk improperly formatted
  1151.      RDCF_DRIVE_ERROR         error in reading or writing disk
  1152.      RDCF_FILE_NOT_FOUND      file not found in RDCF_READ or RDCF_READ_WRITE
  1153.      RDCF_INVALID_DIRECTORY   nonexistent subdirectory in path
  1154.      RDCF_INVALID_SPEC        invalid drive or file specification
  1155.      RDCF_MODE_ERROR          invalid mode
  1156.  
  1157.  
  1158. 8.14. rdcf_read() - Read from a File
  1159. ------------------------------------
  1160.  
  1161. The following function call reads a block of bytes from an open file:
  1162.  
  1163.      n = rdcf_read(fcb, buffer, count);
  1164.  
  1165.      struct rdcf *fcb;   pointer to open file control block
  1166.  
  1167.      void *buffer;       memory buffer to receive data
  1168.  
  1169.      int count;          number of bytes to be read
  1170.  
  1171.      int n;              number of bytes actually read, or a negative
  1172.                          error code
  1173.  
  1174. The file control block must have been successfully opened in mode RDCF_READ or
  1175. RDCF_READ_WRITE by rdcf_open().
  1176.  
  1177. Reading starts at the current file pointer position. If the operation is
  1178. successful, the file pointer is advanced to the byte immediately following the
  1179. last byte read.
  1180.  
  1181. The return value is the number of bytes actually read. If this nonnegative but
  1182. less than the count, the end of the file was encountered.
  1183.  
  1184. Errors are indicated by the following negative return values:
  1185.  
  1186.      return value            meaning
  1187.      ----------------------  ------------------------------------------
  1188.      RDCF_DISK_FORMAT_ERROR  disk improperly formatted
  1189.      RDCF_DRIVE_ERROR        error in reading disk
  1190.      RDCF_FILE_FORMAT_ERROR  corrupt file allocation table
  1191.      RDCF_MODE_ERROR         file mode not RDCF_READ or RDCF_READ_WRITE
  1192.  
  1193.  
  1194. 8.15. rdcf_recover() - Recover Erased Data
  1195. ------------------------------------------
  1196.  
  1197. The following function call creates a new file and puts all unused data
  1198. clusters into it:
  1199.  
  1200.      e = rdcf_recover(fcb, filespec);
  1201.  
  1202.      struct rdcf *fcb;            pointer to file control block
  1203.  
  1204.      char *filespec;              file specification string, with
  1205.                                   terminating \0
  1206.  
  1207.      int e;                       0 if file was successfully opened,
  1208.                                   or negative error code
  1209.  
  1210. When a file is deleted by DOS or RDCF, the information contained in the file is
  1211. not actually erased.  The data clusters containing the information are merely
  1212. marked as unused.  Until these clusters are actually used for other files, the
  1213. information is still there, and can be recovered and assembled into a single
  1214. file by calling this function.
  1215.  
  1216. The file specifications must be for a new file.  If you try to use an existing
  1217. file, this function will return the error code RDCF_ACCESS_DENIED.
  1218.  
  1219. If you specify a file in a subdirectory, it will NOT be lengthened to
  1220. accommodate the new file, as it would be when you call rdcf_open().  That would
  1221. destroy information and partially defeat the purpose of this function.  If
  1222. there is no empty space in the subdirectory, this function will return the
  1223. error code RDCF_DIRECTORY_FULL.
  1224.  
  1225. If this function is successfully called, the new file will contain all the data
  1226. in all unused clusters on the specified drive.  Of course, the unused clusters
  1227. will no longer be unused, and the drive will then be completely full.  If you
  1228. want to edit the information, you may have to copy the file to another drive
  1229. that has room for the backup and scratch files that most text editors require.
  1230. Some kind of editing is usually required because the new file will typically
  1231. contain information from a number of old deleted files or subdirectories, and
  1232. the information will be slightly mixed up if the old files were fragmented.
  1233.  
  1234. Possible return values are as follows:
  1235.  
  1236.      return value             meaning
  1237.      -----------------------  -----------------------------------
  1238.      0                        successful operation
  1239.      RDCF_ACCESS_DENIED       attempt to use an existing file
  1240.      RDCF_DIRECTORY_FULL      insufficient directory space
  1241.      RDCF_DISK_FORMAT_ERROR   disk improperly formatted
  1242.      RDCF_DRIVE_ERROR         error in reading or writing disk
  1243.      RDCF_INVALID_DIRECTORY   nonexistent subdirectory in path
  1244.      RDCF_INVALID_SPEC        invalid drive or file specification
  1245.  
  1246. If RDCF is compiled as a read-only file system, this function is not defined.
  1247.  
  1248.  
  1249. 8.16. rdcf_rename() - Rename a File or Subdirectory
  1250. ---------------------------------------------------
  1251.  
  1252. The following function call changes the name and/or extension of a file or
  1253. subdirectory:
  1254.  
  1255.      e = rdcf_rename(fcb, old_filespec, new_filespec);
  1256.  
  1257.      struct rdcf *fcb;            pointer to file control block
  1258.  
  1259.      char *old_filespec;          old file specification string, with
  1260.                                   terminating \0
  1261.  
  1262.      char *new_filespec;          new name and extension, with
  1263.                                   terminating \0
  1264.  
  1265.      int e;                       0 if file was successfully opened,
  1266.                                   or negative error code
  1267.  
  1268. The new file specification may not begin with a drive specification or
  1269. directory path.
  1270.  
  1271. Possible return values are as follows:
  1272.  
  1273.      return value             meaning
  1274.      -----------------------  ----------------------------------------
  1275.      0                        successful operation
  1276.      RDCF_ACCESS_DENIED       attempt to rename a hidden or system file
  1277.      RDCF_DISK_FORMAT_ERROR   disk improperly formatted
  1278.      RDCF_DRIVE_ERROR         error in reading or writing disk
  1279.      RDCF_FILE_NOT_FOUND      file not found
  1280.      RDCF_INVALID_DIRECTORY   nonexistent subdirectory in path
  1281.      RDCF_INVALID_SPEC        invalid drive or file specification
  1282.      RDCF_RENAMING_ERROR      new file specification is already in use
  1283.  
  1284. If RDCF is compiled as a read-only file system, this function is not defined.
  1285.  
  1286.  
  1287. 8.17. rdcf_seek() - Move a File Pointer
  1288. ---------------------------------------
  1289.  
  1290. The following function call moves a file pointer:
  1291.  
  1292.      e = rdcf_seek(fcb, offset);
  1293.  
  1294.      struct rdcf *fcb;     pointer to open file control block
  1295.  
  1296.      unsigned long offset; desired file pointer offset,
  1297.                            relative to beginning of file
  1298.  
  1299.      int e;                0 for a successful operation,
  1300.                            or a negative error code
  1301.  
  1302. The file control block must have been successfully opened by rdcf_open() in any
  1303. mode.
  1304.  
  1305. If the operation is successful, the function returns zero. The next call on
  1306. rdcf_read() or rcdf_write() will start at the specified position, relative to
  1307. the beginning of the file.
  1308.  
  1309. The file control block entry fcb->position or fcb->file.size can be used to
  1310. convert an offset from the file pointer or end of file to an offset from the
  1311. beginning of the file.
  1312.  
  1313. A file cannot be lengthened by moving the file pointer past the end of the
  1314. file.  To lengthen a file, you must move the file pointer to the end of the
  1315. file and then write enough data to it to make it the desired length.
  1316.  
  1317. Possible return values are as follows:
  1318.  
  1319.      return value            meaning
  1320.      -----------------       -------------------------
  1321.      0                       successful operation
  1322.      RDCF_DISK_FORMAT_ERROR  disk improperly formatted
  1323.      RDCF_DRIVE_ERROR        error in reading disk
  1324.      RDCF_SEEK_OUT_OF_RANGE  offset exceeds file size
  1325.  
  1326.  
  1327. 8.18. rdcf_set_file_information() - Set File Information
  1328. --------------------------------------------------------
  1329.  
  1330. The following function writes new information into a directory entry:
  1331.  
  1332.      e = rdcf_set_file_information(fcb, filespec, index, p);
  1333.  
  1334.      struct rdcf *fcb;            pointer to file control block
  1335.  
  1336.      char *filespec;              directory specification string, with
  1337.                                   terminating \0
  1338.  
  1339.      unsigned index;              index of desired entry (0 = first entry,
  1340.                                   1 = second entry, etc.)
  1341.  
  1342.      struct rdcf_file_information *p;
  1343.                                   pointer to block with new directory
  1344.                                   information
  1345.  
  1346.      int e;                       0 if entry was successfully written,
  1347.                                   or negative error code
  1348.  
  1349. If RDCF_MULTIPLE_DRIVE is defined, the directory specification string for the
  1350. root directory consists of a drive specification alone, such as "A:".
  1351. Otherwise, the empty string ("") represents the root directory.
  1352.  
  1353. This function takes a block of information, converts it to DOS directory
  1354. format, and writes it into the specified directory entry.  The block of
  1355. information is usually supplied by rdcf_get_file_information.  This function is
  1356. used almost exclusively for special disk utilities.
  1357.  
  1358. If p->spec[0] is zero, the entire entry will be cleared to zeros.
  1359.  
  1360. This function will not lengthen a subdirectory if the index is past its current
  1361. end.
  1362.  
  1363. Possible return values are as follows:
  1364.  
  1365.      return value             meaning
  1366.      -----------------------  ----------------------------------------
  1367.      0                        successful operation
  1368.      RDCF_DIRECTORY_FULL      index is past end of directory
  1369.      RDCF_DISK_FORMAT_ERROR   disk improperly formatted
  1370.      RDCF_DRIVE_ERROR         error in reading or writing disk
  1371.      RDCF_INVALID_DIRECTORY   nonexistent subdirectory in path
  1372.      RDCF_INVALID_SPEC        invalid drive or file specification
  1373.  
  1374. If RDCF is compiled as a read-only file system, this function is not defined.
  1375.  
  1376.  
  1377. 8.19. rdcf_set_volume() - Write Volume Name
  1378. -------------------------------------------
  1379.  
  1380. The following function writes a new volume name:
  1381.  
  1382.      e = rdcf_set_volume(fcb, drive_name);
  1383.  
  1384.      struct rdcf *fcb;            pointer to file control block
  1385.  
  1386.      char *drive_name;            string of form "d:name" that specifies
  1387.                                   drive and name, with terminating \0
  1388.  
  1389.      int e;                       0 if name was successfully written,
  1390.                                   or negative error code
  1391.  
  1392. If RDCF_MULTIPLE_DRIVE is defined, the string drive_name begins with a drive
  1393. specification (a drive letter, followed by a colon).  Otherwise, it contains
  1394. only the volume name.  In any case, it is terminated by \0.
  1395.  
  1396. If the volume name is less than 11 characters long, RDCF will pad it with
  1397. blanks at the end before writing it to the disk.
  1398.  
  1399. Notice that the volume name may contain small letters, which are NOT converted
  1400. to capital letters by RDCF.  Volume names in DOS are case-sensitive.  RDCF will
  1401. reject the volume name and return RDCF_INVALID_SPEC if the first character of
  1402. the name is 0xE5, which indicates a deleted file or volume name.
  1403.  
  1404. If there is already a volume name on the drive, it is replaced by the specified
  1405. one.
  1406.  
  1407. The new volume name will bear the current date and time as determined by a call
  1408. on rdcf_get_date_and_time().
  1409.  
  1410.      return value            meaning
  1411.      ----------------------  -----------------------------------
  1412.      0                       successful operation
  1413.      RDCF_DIRECTORY_FULL     insufficient directory space
  1414.      RDCF_DISK_FORMAT_ERROR  disk improperly formatted
  1415.      RDCF_DRIVE_ERROR        error in reading disk
  1416.      RDCF_INVALID_SPEC       invalid drive specification or name
  1417.  
  1418. If RDCF is compiled as a read-only file system, this function is not defined.
  1419.  
  1420.  
  1421. 8.20. rdcf_sort_directory() - Sort a Directory
  1422. ----------------------------------------------
  1423.  
  1424. The following function call sorts a directory:
  1425.  
  1426.      e = rdcf_sort_directory(f, filespec, mode);
  1427.  
  1428.      struct rdcf *fcb;            pointer to file control block
  1429.  
  1430.      char *filespec;              directory specification string, with
  1431.                                   terminating \0
  1432.  
  1433.      int mode;                    code to indicate the kind of sort
  1434.  
  1435.      int e;                       0 if directory was successfully sorted,
  1436.                                   or negative error code
  1437.  
  1438. If RDCF_MULTIPLE_DRIVE is defined, the directory specification string for the
  1439. root directory consists of a drive specification alone, such as "A:".
  1440. Otherwise, the empty string ("") represents the root directory.
  1441.  
  1442. The sorting mode may be any ONE of the following:
  1443.  
  1444.      mode                 manner of sort
  1445.      -------------------  ---------------------------------------------
  1446.      RDCF_EXTENSION_NAME  sort by extension, then among files that have
  1447.                           the same extension, sort by name
  1448.      RDCF_NAME_EXTENSION  sort by name, then among files that have
  1449.                           the same name, sort by extension
  1450.      RDCF_DATE_TIME       sort by date and time (earlier files first)
  1451.      RDCF_SIZE            sort by size (smallest files first)
  1452.  
  1453. The modifier RDCF_REVERSE may be added to any of these modes to sort in the
  1454. opposite order.  For example, RDCF_SIZE+RDCF_REVERSE sorts the files by size,
  1455. but it puts the largest files first.
  1456.  
  1457. Actually, before the function sorts the directory entries, it first divides
  1458. them into five groups and arranges them in the following order:
  1459.  
  1460.      (1) The two system files at the beginning of the root directory and the
  1461.          two special files "." and ".." at the beginning of a subdirectory are
  1462.          always left where they are.
  1463.  
  1464.      (2) The volume label, if any, is put next.
  1465.  
  1466.      (3) The subdirectory entries, if any, are sorted and put next.
  1467.  
  1468.      (4) The file entries are sorted and put next.
  1469.  
  1470.      (5) The entries for deleted files, volume labels and subdirectories, if
  1471.          any, are sorted and put last.
  1472.  
  1473. Within each category, if two entries are identical according to the sorting
  1474. criterion, their relative position is left unchanged.
  1475.  
  1476. Some kind of caching is strongly recommended when using this function.  The
  1477. sorting algorithm is rather primitive one called a "bubble sort", so it may
  1478. take a noticeable amount of time to sort a long directory, even with caching.
  1479.  
  1480. Possible return values are as follows:
  1481.  
  1482.      return value             meaning
  1483.      -----------------------  ----------------------------------------
  1484.      0                        successful operation
  1485.      RDCF_DISK_FORMAT_ERROR   disk improperly formatted
  1486.      RDCF_DRIVE_ERROR         error in reading or writing disk
  1487.      RDCF_INVALID_DIRECTORY   nonexistent subdirectory in path
  1488.      RDCF_INVALID_SPEC        invalid drive or file specification
  1489.  
  1490. If RDCF is compiled as a read-only file system, this function is not defined.
  1491.  
  1492.  
  1493. 8.21. rdcf_undelete() - Restore a Deleted File
  1494. ----------------------------------------------
  1495.  
  1496. When you delete a file, with either DOS or RDCF, the information in the file is
  1497. not erased, although it may become rather difficult to find.
  1498.  
  1499. The following function call restores the original contents of a deleted file,
  1500. to the extent possible:
  1501.  
  1502.      e = rdcf_undelete(fcb, filespec);
  1503.  
  1504.      struct rdcf *fcb;            pointer to file control block
  1505.  
  1506.      char *filespec;              file specification string, with
  1507.                                   terminating \0
  1508.  
  1509.      int e;                       0 if file was even partially recovered,
  1510.                                   or negative error code
  1511.  
  1512. The function will attempt to restore as much of the file as possible.  If only
  1513. part of the file can be restored, the value in fcb->position will indicate how
  1514. much of the file was NOT restored.  If the entire file was restored, this entry
  1515. will be zero. If nothing can be restored because the first data cluster of the
  1516. file is in use by another file, the function will return
  1517. RDCF_UNRECOVERABLE_FILE.
  1518.  
  1519. Even an apparently successful restoration may not restore the original file
  1520. contents.  For example, if another file was written over the original file
  1521. contents and then deleted, RDCF may have no way of knowing that the file
  1522. contents have changed.
  1523.  
  1524. Complete restoration of a file can be assured if the original file was
  1525. unfragmented before it was deleted and nothing has been written to the disk
  1526. after it was deleted.
  1527.  
  1528. Possible return values are as follows:
  1529.  
  1530.      return value             meaning
  1531.      -----------------------  ---------------------------------------
  1532.      0                        fully or partially successful operation
  1533.      RDCF_DIRECTORY_FULL      index is past end of directory
  1534.      RDCF_DISK_FORMAT_ERROR   disk improperly formatted
  1535.      RDCF_DRIVE_ERROR         error in reading or writing disk
  1536.      RDCF_FILE_NOT_FOUND      entry did not represent a deleted file
  1537.      RDCF_INVALID_DIRECTORY   nonexistent subdirectory in path
  1538.      RDCF_INVALID_SPEC        invalid drive or file specification
  1539.      RDCF_UNRECOVERABLE_FILE  none of the file can be restored
  1540.  
  1541. If RDCF is compiled as a read-only file system, this function is not defined.
  1542.  
  1543.  
  1544. 8.22. rdcf_wipe_disk() - Wipe Out Erased Data
  1545. ---------------------------------------------
  1546.  
  1547. The following function call writes nonsense over all unused clusters of the
  1548. specified drive:
  1549.  
  1550.      e = rdcf_wipe_disk(fcb, spec);
  1551.  
  1552.      struct rdcf *fcb;            pointer to file control block
  1553.  
  1554.      char *spec;                  drive specification ("A:", "B:", etc.),
  1555.                                   omitted if RDCF_MULTIPLE_DRIVE is undefined
  1556.  
  1557.      int e;                       0 if operation was successful,
  1558.                                   or negative error code
  1559.  
  1560. When a file is deleted by DOS or RDCF, the information contained in the file is
  1561. not actually erased.  The data clusters containing the information are merely
  1562. marked as unused.  Until these clusters are actually used for other files, the
  1563. information is still there, and can often be recovered by calling
  1564. rdcf_undelete() or rdcf_recover() or by using a file recovery utility.
  1565.  
  1566. For security reasons, you may want to make sure your erased files are really
  1567. erased.  This function does that by writing nonsense into every cluster marked
  1568. as unused.
  1569.  
  1570. The information is not completely destroyed. It may be possible to read some of
  1571. it by subjecting the disk to a special analysis in a laboratory, but it cannot
  1572. be read by an ordinary file recovery utility.
  1573.  
  1574. Even erasing every unused cluster won't necessarily remove all the information
  1575. from erased files.  There may be unused sectors at the ends of files that are
  1576. not erased.  The last cluster of such a file is not marked as unused, because
  1577. part of it is being used.  But the part that is not being used may contain
  1578. information from an older file that did use the entire cluster.
  1579.  
  1580. Possible return values are as follows:
  1581.  
  1582.      return value             meaning
  1583.      -----------------------  ------------------------------------------
  1584.      0                        fully or partially successful operation
  1585.      RDCF_DISK_FORMAT_ERROR   disk improperly formatted
  1586.      RDCF_DRIVE_ERROR         error in reading or writing disk
  1587.      RDCF_INVALID_SPEC        invalid drive specification
  1588.  
  1589. If RDCF is compiled as a read-only file system, this function is not defined.
  1590.  
  1591.  
  1592. 8.23. rdcf_write() - Write to a File
  1593. ------------------------------------
  1594.  
  1595. The following function call writes a block of bytes to an open file:
  1596.  
  1597.      n = rdcf_write(fcb, buffer, count);
  1598.  
  1599.      struct rdcf *fcb;   pointer to open file control block
  1600.  
  1601.      void *buffer;       memory buffer to supply data
  1602.  
  1603.      int count;          number of bytes to be written
  1604.  
  1605.      int n;              number of bytes actually written, or a negative
  1606.                          error code
  1607.  
  1608. The file control block must have been successfully opened in mode RDCF_CREATE
  1609. or RDCF_READ_WRITE by rdcf_open().
  1610.  
  1611. Writing starts at the current file pointer position. If the operation is
  1612. successful, the file pointer is advanced to the byte immediately following the
  1613. last byte written.
  1614.  
  1615. If necessary, the file is lengthened to accommodate the bytes being written.
  1616.  
  1617. The return value is the number of bytes actually written. If this is
  1618. nonnegative but less than the count, there was insufficient disk space to write
  1619. all the data.
  1620.  
  1621. Other errors are indicated by the following negative return values:
  1622.  
  1623.      return value            meaning
  1624.      ---------------------   --------------------------------------------
  1625.      RDCF_DISK_FORMAT_ERROR  disk improperly formatted
  1626.      RDCF_DRIVE_ERROR        error in reading or writing disk
  1627.      RDCF_FILE_FORMAT_ERROR  corrupt file allocation table
  1628.      RDCF_MODE_ERROR         file mode not RDCF_CREATE or RDCF_READ_WRITE
  1629.  
  1630. This function also sets an internal flag to indicate that the file has been
  1631. written, which causes RDCF to update the directory when the file is later
  1632. closed. If the count is zero, setting the flag is all it does.
  1633.  
  1634. If RDCF is compiled as a read-only file system, this function is not defined.
  1635.  
  1636.  
  1637.          ----------------end-of-author's-documentation---------------
  1638.  
  1639.                          Software Library Information:
  1640.  
  1641.                     This disk copy provided as a service of
  1642.  
  1643.                            Public (software) Library
  1644.  
  1645.          We are not the authors of this program, nor are we associated
  1646.          with the author in any way other than as a distributor of the
  1647.          program in accordance with the author's terms of distribution.
  1648.  
  1649.          Please direct shareware payments and specific questions about
  1650.          this program to the author of the program, whose name appears
  1651.          elsewhere in  this documentation. If you have trouble getting
  1652.          in touch with the author,  we will do whatever we can to help
  1653.          you with your questions. All programs have been tested and do
  1654.          run.  To report problems,  please use the form that is in the
  1655.          file PROBLEM.DOC on many of our disks or in other written for-
  1656.          mat with screen printouts, if possible.  PsL cannot debug pro-
  1657.          programs over the telephone, though we can answer questions.
  1658.  
  1659.          Disks in the PsL are updated  monthly,  so if you did not get
  1660.          this disk directly from the PsL, you should be aware that the
  1661.          files in this set may no longer be the current versions. Also,
  1662.          if you got this disk from another vendor and are having prob-
  1663.          lems,  be aware that  some files may have become corrupted or
  1664.          lost by that vendor. Get a current, working disk from PsL.
  1665.  
  1666.          For a copy of the latest monthly software library newsletter
  1667.          and a list of the 4,000+ disks in the library, call or write
  1668.  
  1669.                            Public (software) Library
  1670.                                  P.O.Box 35705
  1671.                             Houston, TX 77235-5705
  1672.  
  1673.                                  Orders only:
  1674.                                 1-800-2424-PSL
  1675.                               MC/Visa/AmEx/Discover
  1676.  
  1677.                           Outside of U.S. or in Texas
  1678.                           or for general information,
  1679.                               Call 1-713-524-6394                 
  1680.